from model.item import ItemDao
from model.company import Company, CompanyDao
from model.item_picture import ItemPictureDao
from service.item_picture import ItemPictureService
from lib.validator import Validator
from lib.form import Form
from bson.objectid import ObjectId
from bson.dbref import DBRef

from service import Service

class ItemService(Service):
    def __init__(self):
        self.dao = ItemDao()
        self.company_dao = CompanyDao()
        self.item_picture_dao = ItemPictureDao()
    
    def get_default_picture_path(self, item):
        """Arguments:
            item -- must be Model class
        """
        company = self.company_dao.find_one({'_id':item.company['_id']})
        pic = self.item_picture_dao.find_one({'item_ref': DBRef('items',item._id)})
        
        if pic is None:
            picture_serv = ItemPictureService(company.name, item._id)
            return picture_serv.builtin_path
        else:
            return pic.fpath
        
    def get_items(self, query={}):
        """ Get items for display
        """
        items = []
        _items = self.dao.find(query)
        for _item in _items:
            fpath = self.get_default_picture_path(_item)    
            items.append({"iid":str(_item._id),
                          "name":_item.name, 
                          "description":_item.description, 
                          "price":_item.price,
                          "pic_fpath":fpath})
        return items

    def get_items_by_company(self, company):
        """ Get items for display
        """
        if isinstance(company, Company):
            company_ref = DBRef('companies', company._id)
            return self.get_items({'company_ref':company_ref})
        elif isinstance(company, dict):
            _company = self.company_dao.find_one({'name':company['name']})
            company_ref = DBRef('companies', _company._id)
            return self.get_items({'company_ref':company_ref})
        
    def submit_item(self, inputs):
        """
           Return:
        The '_id' value of to_save or [None] if manipulate is False and to_save has no _id field.
        """
        # Submit item           
        _dict = {'name':inputs['name'],
                 'description': inputs['description'],
                 'price':inputs['price'],
                 'company_ref': inputs['company_ref']}
        if inputs['iid']!='':
            _dict['_id']= ObjectId(inputs['iid'])
        
          
        return self.dao.save(_dict)


class ItemValidator(Validator):
    def __init__(self):
        Validator.__init__(self)
              
        self.rules = {'name': { 
                                'required' : [None, True],
                                'minlength':[None, 1],
                                'maxlength':[None, 256]
                                },
                      'description': { 
                                'maxlength':[None, 256]
                                },
                      'price': { 
                                'numeric' : [None, True]
                                }
        }

    
class ItemForm(Form):
    """ Submit user form
    """
    def __init__(self):
        """Only accept POST request
        """
        Form.__init__(self)
        self.validator = ItemValidator()
        
        if self.is_submitted():
            self.raw_inputs = self.get_raw_inputs()
            self.inputs = self.get_inputs(self.raw_inputs)
            self.errors = self.validator.validate(self.inputs)

    def get_inputs(self, raw_inputs):                
        """ Convert inputs type
        """
        company_dao = CompanyDao()
        company = company_dao.find_one({'name':raw_inputs['company_name']})
        company_dbref = DBRef('companies', company._id )
        
        return {'mode': raw_inputs['mode'],
                'iid':raw_inputs['iid'],
                'name': raw_inputs['name'],
               'description': raw_inputs['description'],
               'price': float(raw_inputs['price']),
               'company_ref': company_dbref   
        }
        
    def has_error(self):
        return self.errors != []
